import time
import logging
from collections import defaultdict

from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from starlette.middleware.base import BaseHTTPMiddleware

from config import config

# logger = logging.getLogger("uvicorn.access")
# logger.setLevel(logging.WARNING)
# logger.disabled = True


class RateLimitMiddleware(BaseHTTPMiddleware):
    def __init__(self, app: FastAPI):
        super().__init__(app)
        self.request_records: dict[str, float] = defaultdict(float)

    async def dispatch(self, request: Request, call_next):
        if request.url.path in ["/docs", "/docs#", "/openapi.json", "/favicon.ico"]:
            return await call_next(request)
        ip = request.client.host
        current_time = time.time()
        if current_time - self.request_records[ip] < config.VISIT_LIMIT_TIME:
            return Response(status_code=429, content="You're making request too frequently")
        response = await call_next(request)
        self.request_records[ip] = current_time
        return response


def my_logger(message) -> None:
    print(f"{message}")


def init_middleware(app: FastAPI):
    @app.middleware("http")
    async def count_time(request: Request, call_next):
        start_time = time.time()
        response = await call_next(request)
        response_time = time.time() - start_time
        print(f"{request.url} has done in {response_time:.6f}s")
        return response

    @app.middleware("http")
    async def logging(request: Request, call_next):
        message = f"{request.client.host}:{request.client.port}  {request.method}  {request.url} {request.headers['Host']}"
        my_logger(message)
        return await call_next(request)

    app.add_middleware(RateLimitMiddleware)
    app.add_middleware(
        CORSMiddleware,
        allow_origins=config.CORS_ALLOWED_ORIGINS,
        allow_credentials=config.CORS_ALLOW_CREDENTIALS,
        allow_methods=config.CORS_ALLOW_METHODS,
        allow_headers=config.CORS_ALLOW_HEADERS,
    )
